package com.ruoyi.business.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import com.ruoyi.business.domain.LocationInfo;
import com.ruoyi.business.domain.NumberManagement;
import com.ruoyi.business.domain.TextReader;
import com.ruoyi.business.domain.vo.ModelingManagementVO;
import com.ruoyi.business.mapper.LocationInfoMapper;
import com.ruoyi.business.mapper.ModelingManagementMapper;
import com.ruoyi.business.mapper.NumberManagementMapper;
import com.ruoyi.business.service.ILocationInfoService;
import com.ruoyi.business.service.INumberManagementService;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.BigDecimalUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import cn.hutool.core.io.file.FileReader;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.SQLOutput;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 编号管理Service业务层处理
 *
 * @author yangmeng
 * @date 2023-06-01
 */
@Service
public class NumberManagementServiceImpl implements INumberManagementService {

    @Value("${ruoyi.profile}")
    private String uploadFolder;

    @Autowired
    private NumberManagementMapper numberManagementMapper;

    @Autowired
    private LocationInfoMapper locationInfoMapper;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private ModelingManagementMapper modelingManagementMapper;

    @Autowired
    private ILocationInfoService locationInfoService;

    /**
     * 查询编号管理
     *
     * @param numberId 编号管理主键
     * @return 编号管理
     */
    @Override
    public NumberManagement selectNumberManagementByNumberId(Long numberId) {
        return numberManagementMapper.selectNumberManagementByNumberId(numberId);
    }

    /**
     * 查询编号管理列表
     *
     * @param numberManagement 编号管理
     * @return 编号管理
     */
    @Override
    public List<NumberManagement> selectNumberManagementList(NumberManagement numberManagement) {
        return numberManagementMapper.selectNumberManagementList(numberManagement);
    }

    /**
     * 新增编号管理
     *
     * @param numberManagement 编号管理
     * @return 结果
     */
    @Override
    public int insertNumberManagement(NumberManagement numberManagement) {
        numberManagement.setCreateTime(DateUtils.getNowDate());
        numberManagement.setCreateBy(SecurityUtils.getUserId());
        numberManagement.setRemark("0");
        int result = numberManagementMapper.insertNumberManagement(numberManagement);
        if (result > 0) {
            threadPoolTaskExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        readFile(numberManagement);
                    } catch (Exception e) {
                        System.out.println(e.toString());
                    } finally {
                        numberManagement.setRemark("1");
                        numberManagementMapper.updateNumberManagement(numberManagement);
                    }
                }
            });
        }
        return result;
    }

    /**
     * 修改编号管理
     *
     * @param numberManagement 编号管理
     * @return 结果
     */
    @Override
    public int updateNumberManagement(NumberManagement numberManagement) {
        numberManagement.setUpdateTime(DateUtils.getNowDate());
        numberManagement.setUpdateBy(SecurityUtils.getUserId());
        numberManagement.setRemark("0");
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    readFile(numberManagement);
                } catch (Exception e) {
                    System.out.println(e.toString());
                } finally {
                    numberManagement.setRemark("1");
                    numberManagementMapper.updateNumberManagement(numberManagement);
                }
            }
        });
        return numberManagementMapper.updateNumberManagement(numberManagement);
    }


    /**
     * 批量删除编号管理
     *
     * @param numberIds 需要删除的编号管理主键
     * @return 结果
     */
    @Override
    public int deleteNumberManagementByNumberIds(Long[] numberIds) {
        return numberManagementMapper.deleteNumberManagementByNumberIds(numberIds);
    }

    /**
     * 删除编号管理信息
     *
     * @param numberId 编号管理主键
     * @return 结果
     */
    @Override
    public int deleteNumberManagementByNumberId(Long numberId) {
        return numberManagementMapper.deleteNumberManagementByNumberId(numberId);
    }

    /**
     * 校验编号项目名称是否唯一
     *
     * @param numberManagement 编号项目信息
     * @return 结果
     */
    @Override
    public boolean checkNumberNameUnique(NumberManagement numberManagement)
    {
        Long numberId = StringUtils.isNull(numberManagement.getNumberId()) ? -1L : numberManagement.getNumberId();
        NumberManagement info = numberManagementMapper.checkNumberNameUnique(numberManagement.getNumberName());
        if (StringUtils.isNotNull(info) && info.getNumberId().longValue() != numberId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 读取配置文件
     * @param numberManagement
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void readFile(NumberManagement numberManagement) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("work_dir", numberManagement.getCadUrl());
        System.out.println("========= 调用Python开始=========");
        String filePath = HttpRequest.post("http://192.16.28.150:8501").form(paramMap).execute().body();
        System.out.println("坐标文件"+ filePath + "=========");
        FileReader fileReader;
        fileReader = new FileReader(filePath);
        List<String> list = fileReader.readLines();
        List<TextReader> readerList = new ArrayList<>();
        for (String str : list) {
            if (str.contains("Longitude") || str.contains("Latitude") || str.contains("Elevation") || StringUtils.isEmpty(str) || str.contains("please check")) {
                continue;
            }
            String[] filed =  StringUtils.splitPreserveAllTokens(str, ",");
            TextReader textReader;
            try {
                textReader = ReflectUtils.getMappingPo(TextReader.class, filed);
                textReader.setCoordinate(textReader.getLongitude() + "," + textReader.getLatitude() + "," + textReader.getElevation());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            readerList.add(textReader);
        }
        // 编号项目ID
        Long numberId = numberManagement.getNumberId();
        // 所属电站ID
        Long stationId = numberManagement.getStationId();
        // 支架列数
        Integer bracketRow = numberManagement.getBracketColumn();
        // 支架行数
        Integer bracketColumn = numberManagement.getBracketRow();
        // 组件编号顺序
        String assemblyOrder = numberManagement.getAssemblyOrder();
        // 组串编号顺序
        String seriesOrder = numberManagement.getSeriesOrder();
        String type = numberManagement.getType();
        // 删除项目编号坐标信息
        locationInfoMapper.deleteLocationInfoByNumberId(numberId);
        readerList.stream().collect(Collectors.groupingBy(TextReader::getName)).forEach((key, value) -> {
            if ("0".equals(type)) {
                if (key.contains("@")) {
                    String[] arr1 = key.split("@");
                    for (String name : arr1) {
                        int index = name.indexOf("N");
                        if (index > 0 && name.charAt(index - 1) != '-') {
                            name = name.replace("N", "-N");
                        }
                        String[] nameArr = name.split("-");
                        StringBuffer ancestors = new StringBuffer();
                        ancestors.append(0).append(",");
                        String pName = "";
                        Long pid = 0L;
                        for (int i = 0; i < nameArr.length; i++) {
                            LocationInfo locationInfo = new LocationInfo();
                            if (i == nameArr.length -1) {
                                locationInfo.setName(pName + nameArr[i]);
                                locationInfo.setNumberId(numberId);
                                locationInfo.setStationId(stationId);
                                locationInfo.setBracketLine(bracketColumn);
                                locationInfo.setBracketRow(bracketRow);
                                locationInfo.setSeriesOrder(seriesOrder);
                                locationInfo.setAssemblyOrder(assemblyOrder);
                                locationInfo.setAncestors(ancestors.toString());
                                locationInfo.setPid(pid);
                                locationInfo.setCoordinateOne(value.get(0).getCoordinate());
                                locationInfo.setCoordinateTwo(value.get(1).getCoordinate());
                                locationInfo.setCoordinateThree(value.get(2).getCoordinate());
                                locationInfo.setCoordinateFour(value.get(3).getCoordinate());
                                locationInfo.setCoordinateFive(BigDecimalUtils.add(value.get(0).getLongitude(), value.get(1).getLongitude(), value.get(2).getLongitude(), value.get(3).getLongitude()) + "," +
                                        BigDecimalUtils.add(value.get(0).getLatitude(), value.get(1).getLatitude(), value.get(2).getLatitude(), value.get(3).getLatitude()) + ",0");
                                locationInfo.setRemark("0");
                                LocationInfo locationInfoDb = locationInfoMapper.checkName(locationInfo);
                                if (locationInfoDb == null) {
                                    locationInfoMapper.insertLocationInfo(locationInfo);
                                    pid = locationInfo.getLocationId();
                                    ancestors.append(locationInfo.getLocationId()).append(",");
                                } else {
                                    pid = locationInfoDb.getLocationId();
                                    ancestors.append(locationInfoDb.getLocationId()).append(",");
                                }
                                TextReader[][] array = locationInfoService.calcGPS(bracketColumn, bracketRow, value);
                                if (nameArr[i].contains("~")){
                                    locationInfoService.seriesNumber(value, locationInfo);
                                } else {
                                    LocationInfo locationInfoA = new LocationInfo();
                                    locationInfoA.setName(pName + nameArr[i]);
                                    locationInfoA.setNumberId(numberId);
                                    locationInfoA.setStationId(stationId);
                                    locationInfoA.setSeriesOrder(seriesOrder);
                                    locationInfoA.setAssemblyOrder(assemblyOrder);
                                    locationInfoA.setBracketLine(1);
                                    locationInfoA.setBracketRow(bracketRow);
                                    locationInfoA.setAncestors(ancestors.toString());
                                    locationInfoA.setPid(pid);
                                    int index1 = 0;
                                    int index2 = 0;
                                    // 组串编号
                                    if ("0".equals(seriesOrder)) {
                                        index1 = 0;
                                        index2 = 1;
                                    } else if ("0".equals(seriesOrder)) {
                                        index1 = bracketColumn;
                                        index2 = bracketColumn - 1;
                                    }
                                    locationInfoA.setCoordinateOne(array[index1][0].getLongitude() + "," + array[index1][0].getLatitude() + "," + array[index1][0].getElevation());
                                    locationInfoA.setCoordinateTwo(array[index2][0].getLongitude() + "," + array[index2][0].getLatitude() + "," + array[index2][0].getElevation());
                                    locationInfoA.setCoordinateThree(array[index1][bracketRow].getLongitude() + "," + array[index1][bracketRow].getLatitude() + "," + array[index1][bracketRow].getElevation());
                                    locationInfoA.setCoordinateFour(array[index2][bracketRow].getLongitude() + "," + array[index2][bracketRow].getLatitude() + "," + array[index2][bracketRow].getElevation());
                                    locationInfoA.setCoordinateFive(BigDecimalUtils.add(array[index1][0].getLongitude(), array[index2][0].getLongitude(), array[index1][bracketRow].getLongitude(), array[index2][bracketRow].getLongitude()) + "," +
                                            BigDecimalUtils.add(array[index1][0].getLatitude(), array[index2][0].getLatitude(), array[index1][bracketRow].getLatitude(), array[index2][bracketRow].getLatitude()) + ",0");
                                    locationInfoMapper.insertLocationInfo(locationInfoA);
                                    List<TextReader> textReaders = new ArrayList<>();
                                    textReaders.add(array[index1][0]);
                                    textReaders.add(array[index2][0]);
                                    textReaders.add(array[index1][bracketRow]);
                                    textReaders.add(array[index2][bracketRow]);
                                    // 组件编号
                                    locationInfoService.assemblyNumber(textReaders, locationInfoA);
                                }
                            } else{
                                locationInfo.setName(pName + nameArr[i]);
                                locationInfo.setNumberId(numberId);
                                locationInfo.setStationId(stationId);
                                locationInfo.setBracketLine(bracketColumn);
                                locationInfo.setBracketRow(bracketRow);
                                locationInfo.setSeriesOrder(seriesOrder);
                                locationInfo.setAssemblyOrder(assemblyOrder);
                                locationInfo.setAncestors(ancestors.toString());
                                locationInfo.setPid(pid);
                                LocationInfo locationInfoDb = locationInfoMapper.checkName(locationInfo);
                                if (locationInfoDb == null) {
                                    locationInfoMapper.insertLocationInfo(locationInfo);
                                    pid = locationInfo.getLocationId();
                                    ancestors.append(locationInfo.getLocationId()).append(",");
                                    pName = locationInfo.getName() + "-";
                                } else {
                                    pid = locationInfoDb.getLocationId();
                                    ancestors.append(locationInfoDb.getLocationId()).append(",");
                                    pName = locationInfoDb.getName() + "-";
                                }
                            }
                        }
                    }
                } else {
                    int index = key.indexOf("N");
                    if (index > 0 && key.charAt(index - 1) != '-') {
                        key = key.replace("N", "-N");
                    }
                    String[] nameArr = key.split("-");
                    StringBuffer ancestors = new StringBuffer();
                    ancestors.append(0).append(",");
                    String pName = "";
                    Long pid = 0L;
                    for (int i = 0; i < nameArr.length; i++) {
                        LocationInfo locationInfo = new LocationInfo();
                        if (i == nameArr.length -1) {
                            locationInfo.setName(pName + nameArr[i]);
                            locationInfo.setNumberId(numberId);
                            locationInfo.setStationId(stationId);
                            locationInfo.setBracketLine(bracketColumn);
                            locationInfo.setBracketRow(bracketRow);
                            locationInfo.setSeriesOrder(seriesOrder);
                            locationInfo.setAssemblyOrder(assemblyOrder);
                            locationInfo.setAncestors(ancestors.toString());
                            locationInfo.setPid(pid);
                            locationInfo.setCoordinateOne(value.get(0).getCoordinate());
                            locationInfo.setCoordinateTwo(value.get(1).getCoordinate());
                            locationInfo.setCoordinateThree(value.get(2).getCoordinate());
                            locationInfo.setCoordinateFour(value.get(3).getCoordinate());
                            locationInfo.setCoordinateFive(BigDecimalUtils.add(value.get(0).getLongitude(), value.get(1).getLongitude(), value.get(2).getLongitude(), value.get(3).getLongitude()) + "," +
                                    BigDecimalUtils.add(value.get(0).getLatitude(), value.get(1).getLatitude(), value.get(2).getLatitude(), value.get(3).getLatitude()) + ",0");
                            locationInfo.setRemark("0");
                            LocationInfo locationInfoDb = locationInfoMapper.checkName(locationInfo);
                            if (locationInfoDb == null) {
                                locationInfoMapper.insertLocationInfo(locationInfo);
                                pid = locationInfo.getLocationId();
                                ancestors.append(locationInfo.getLocationId()).append(",");
                            } else {
                                pid = locationInfoDb.getLocationId();
                                ancestors.append(locationInfoDb.getLocationId()).append(",");
                            }
                            if (nameArr[i].contains("~")){
                                // 组串编号
                                locationInfoService.seriesNumber(value, locationInfo);
                            } else {
                                locationInfo.setBracketLine(1);
                                // 组件编号
                                if (bracketColumn == 1) {
                                    locationInfo.setInitialValue(1);
                                    locationInfo.setEndValue(bracketRow);
                                    locationInfoService.assemblyNumber(value, locationInfo);
                                } else if (bracketColumn == 2) {
                                    String assemblyOrder1 = assemblyOrder;
                                    String assemblyOrder2 = assemblyOrder;
                                    if ("2".equals(assemblyOrder)) {
                                        assemblyOrder1 = "0";
                                        assemblyOrder2 = "1";
                                    } else if ("3".equals(assemblyOrder)) {
                                        assemblyOrder1 = "1";
                                        assemblyOrder2 = "0";
                                    }
                                    TextReader[][] textReaders = locationInfoService.calcGPS(bracketColumn, bracketRow, value);
                                    List<TextReader> list1 = new ArrayList<>();
                                    list1.add(textReaders[1][0]);
                                    list1.add(textReaders[2][0]);
                                    list1.add(textReaders[1][bracketRow]);
                                    list1.add(textReaders[2][bracketRow]);
                                    locationInfo.setInitialValue(1);
                                    locationInfo.setEndValue(bracketRow);
                                    locationInfo.setAssemblyOrder(assemblyOrder1);
                                    locationInfoService.assemblyNumber(list1, locationInfo);

                                    List<TextReader> list2 = new ArrayList<>();
                                    list2.add(textReaders[1][0]);
                                    list2.add(textReaders[0][0]);
                                    list2.add(textReaders[1][bracketRow]);
                                    list2.add(textReaders[0][bracketRow]);
                                    locationInfo.setInitialValue(bracketRow + 1);
                                    locationInfo.setEndValue(bracketRow + bracketRow);
                                    locationInfo.setAssemblyOrder(assemblyOrder2);
                                    locationInfoService.assemblyNumber(list2, locationInfo);
                                }
                            }
                        } else {
                            locationInfo.setName(pName + nameArr[i]);
                            locationInfo.setNumberId(numberId);
                            locationInfo.setStationId(stationId);
                            locationInfo.setBracketLine(bracketColumn);
                            locationInfo.setBracketRow(bracketRow);
                            locationInfo.setSeriesOrder(seriesOrder);
                            locationInfo.setAssemblyOrder(assemblyOrder);
                            locationInfo.setAncestors(ancestors.toString());
                            locationInfo.setPid(pid);
                            LocationInfo locationInfoDb = locationInfoMapper.checkName(locationInfo);
                            if (locationInfoDb == null) {
                                locationInfoMapper.insertLocationInfo(locationInfo);
                                pid = locationInfo.getLocationId();
                                ancestors.append(locationInfo.getLocationId()).append(",");
                                pName = locationInfo.getName() + "-";
                            } else {
                                pid = locationInfoDb.getLocationId();
                                ancestors.append(locationInfoDb.getLocationId()).append(",");
                                pName = locationInfoDb.getName() + "-";
                            }
                        }
                    }
                }
            } else if ("1".equals(type)) {
                locationInfoService.numberType1(value, key, numberManagement);
            }
        });
    }
}
